Eliminate tss - tss is meaningless in a paravirtualized kernel
authorcl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Mon, 20 Feb 2006 14:46:14 +0000 (14:46 +0000)
committercl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Mon, 20 Feb 2006 14:46:14 +0000 (14:46 +0000)
and consumes 25% of the per-cpu area.
Add CONFIG_X86_NO_TSS to exclude all code which references tss.
Add CONFIG_X86_SYSENTER to conditionally include support for sysenter.
Change CONFIG_DOUBLEFAULT to depend on !CONFIG_X86_NO_TSS.
(sysenter and doublefault need tss).

Based on a patch by Jan Beulich <JBeulich@novell.com>
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
12 files changed:
linux-2.6-xen-sparse/arch/i386/Kconfig
linux-2.6-xen-sparse/arch/i386/kernel/Makefile
linux-2.6-xen-sparse/arch/i386/kernel/asm-offsets.c
linux-2.6-xen-sparse/arch/i386/kernel/cpu/common-xen.c
linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S
linux-2.6-xen-sparse/arch/i386/kernel/init_task-xen.c
linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c
linux-2.6-xen-sparse/arch/i386/kernel/sysenter.c
linux-2.6-xen-sparse/arch/i386/kernel/vm86.c
linux-2.6-xen-sparse/arch/i386/kernel/vsyscall.S
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/desc.h
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/processor.h

index cfcdff031744435813e3550a8046559d5dc871c6..88e1e1b98e07f6c6714d64b177f236e030017430 100644 (file)
@@ -780,7 +780,7 @@ config HOTPLUG_CPU
 config DOUBLEFAULT
        default y
        bool "Enable doublefault exception handler" if EMBEDDED
-       depends on !XEN
+       depends on !X86_NO_TSS
        help
           This option allows trapping of rare doublefault exceptions that
           would otherwise cause a system to silently reboot. Disabling this
@@ -1176,6 +1176,16 @@ config X86_TRAMPOLINE
        depends on X86_SMP || (X86_VOYAGER && SMP)
        default y
 
+config X86_NO_TSS
+       bool
+       depends on X86_XEN
+       default y
+
+config X86_SYSENTER
+       bool
+       depends on !X86_NO_TSS
+       default y
+
 config KTIME_SCALAR
        bool
        default y
index 369c00bdd8f8961d319f7f77d723cd86bd89ff93..32b54bd7eaa9d3396cc0cc2be7914799c0bb3e91 100644 (file)
@@ -49,11 +49,13 @@ else
 vsyscall_note := vsyscall-note.o
 endif
 
+VSYSCALL_TYPES-y                       := int80
+VSYSCALL_TYPES-$(CONFIG_X86_SYSENTER)  += sysenter
 # vsyscall.o contains the vsyscall DSO images as __initdata.
 # We must build both images before we can assemble it.
 # Note: kbuild does not track this dependency due to usage of .incbin
-$(obj)/vsyscall.o: $(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so
-targets += $(foreach F,int80 sysenter,vsyscall-$F.o vsyscall-$F.so)
+$(obj)/vsyscall.o: $(foreach F,$(VSYSCALL_TYPES-y),$(obj)/vsyscall-$F.so)
+targets += $(foreach F,$(VSYSCALL_TYPES-y),vsyscall-$F.o vsyscall-$F.so)
 targets += $(vsyscall_note) vsyscall.lds
 
 # The DSO images are built using a special linker script.
@@ -81,7 +83,8 @@ $(obj)/built-in.o: ld_flags += -R $(obj)/vsyscall-syms.o
 
 SYSCFLAGS_vsyscall-syms.o = -r
 $(obj)/vsyscall-syms.o: $(src)/vsyscall.lds \
-                       $(obj)/vsyscall-sysenter.o $(obj)/$(vsyscall_note) FORCE
+                       $(foreach F,$(VSYSCALL_TYPES-y),$(obj)/vsyscall-$F.o) \
+                       $(obj)/$(vsyscall_note) FORCE
        $(call if_changed,syscall)
 
 ifdef CONFIG_XEN
index 36d66e2077d0495be04b435eb7602520e967cbe5..fa4f25dada73213a6dee353cb16e19b65e6518d8 100644 (file)
@@ -63,9 +63,11 @@ void foo(void)
        OFFSET(pbe_orig_address, pbe, orig_address);
        OFFSET(pbe_next, pbe, next);
 
+#ifdef CONFIG_X86_SYSENTER
        /* Offset from the sysenter stack to tss.esp0 */
        DEFINE(TSS_sysenter_esp0, offsetof(struct tss_struct, esp0) -
                 sizeof(struct tss_struct));
+#endif
 
        DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
        DEFINE(VSYSCALL_BASE, __fix_to_virt(FIX_VSYSCALL));
index 5d06b3a4a2303ad34b3c97faa84aaa66a9c1287b..4d646fe16fcd00685991c4912c2e685c26382636 100644 (file)
@@ -595,7 +595,9 @@ void __cpuinit cpu_gdt_init(struct Xgt_desc_struct *gdt_descr)
 void __cpuinit cpu_init(void)
 {
        int cpu = smp_processor_id();
+#ifdef CONFIG_DOUBLEFAULT
        struct tss_struct * t = &per_cpu(init_tss, cpu);
+#endif
        struct thread_struct *thread = &current->thread;
 
        if (cpu_test_and_set(cpu, cpu_initialized)) {
index d012631501515a8a10805ac2f2a7898492c3a845..0df22a8675481be11486e4aed54e23dbdc59114d 100644 (file)
@@ -223,6 +223,7 @@ need_resched:
        jmp need_resched
 #endif
 
+#ifdef CONFIG_X86_SYSENTER
 /* SYSENTER_RETURN points to after the "sysenter" instruction in
    the vsyscall page.  See vsyscall-sysentry.S, which defines the symbol.  */
 
@@ -270,6 +271,7 @@ sysenter_past_esp:
        xorl %ebp,%ebp
        sti
        sysexit
+#endif /* CONFIG_X86_SYSENTER */
 
 
        # system call handler stub
@@ -662,6 +664,7 @@ ENTRY(device_not_available)
        call math_state_restore
        jmp ret_from_exception
 
+#ifdef CONFIG_X86_SYSENTER
 /*
  * Debug traps and NMI can happen at the one SYSENTER instruction
  * that sets up the real kernel stack. Check here, since we can't
@@ -683,12 +686,15 @@ label:                                            \
        pushfl;                                 \
        pushl $__KERNEL_CS;                     \
        pushl $sysenter_past_esp
+#endif /* CONFIG_X86_SYSENTER */
 
 KPROBE_ENTRY(debug)
+#ifdef CONFIG_X86_SYSENTER
        cmpl $sysenter_entry,(%esp)
        jne debug_stack_correct
        FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn)
 debug_stack_correct:
+#endif /* !CONFIG_X86_SYSENTER */
        pushl $-1                       # mark this as an int
        SAVE_ALL
        xorl %edx,%edx                  # error code 0
index c0203975017a6f7081e247898d2b46f68032aa28..c4da1cce828fab18f9eb4bb02beec53cef3b2330 100644 (file)
@@ -41,9 +41,11 @@ struct task_struct init_task = INIT_TASK(init_task);
 
 EXPORT_SYMBOL(init_task);
 
+#ifndef CONFIG_X86_NO_TSS
 /*
  * per-CPU TSS segments. Threads are completely 'soft' on Linux,
  * no more per-task TSS's.
  */ 
 DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_internodealigned_in_smp = INIT_TSS;
+#endif
 
index b193ece654b52547dedf34a3d49b7479e4cc0a25..3f6e31b47227c1ff90b44cbd3390bd635d81c5ab 100644 (file)
@@ -518,7 +518,9 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
        struct thread_struct *prev = &prev_p->thread,
                                 *next = &next_p->thread;
        int cpu = smp_processor_id();
+#ifndef CONFIG_X86_NO_TSS
        struct tss_struct *tss = &per_cpu(init_tss, cpu);
+#endif
        physdev_op_t iopl_op, iobmp_op;
        multicall_entry_t _mcl[8], *mcl = _mcl;
 
@@ -543,10 +545,9 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
         * Reload esp0.
         * This is load_esp0(tss, next) with a multicall.
         */
-       tss->esp0 = next->esp0;
        mcl->op      = __HYPERVISOR_stack_switch;
-       mcl->args[0] = tss->ss0;
-       mcl->args[1] = tss->esp0;
+       mcl->args[0] = __KERNEL_DS;
+       mcl->args[1] = next->esp0;
        mcl++;
 
        /*
index 0bada1870bdf5691631e10558bf43cbb350691a1..3bd61e7bf0b3def7a221b6ba0f08ad81b0e3805a 100644 (file)
@@ -23,6 +23,7 @@ extern asmlinkage void sysenter_entry(void);
 
 void enable_sep_cpu(void)
 {
+#ifdef CONFIG_X86_SYSENTER
        int cpu = get_cpu();
        struct tss_struct *tss = &per_cpu(init_tss, cpu);
 
@@ -37,6 +38,7 @@ void enable_sep_cpu(void)
        wrmsr(MSR_IA32_SYSENTER_ESP, tss->esp1, 0);
        wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) sysenter_entry, 0);
        put_cpu();      
+#endif
 }
 
 /*
@@ -52,16 +54,18 @@ int __init sysenter_setup(void)
 
        __set_fixmap(FIX_VSYSCALL, __pa(page), PAGE_READONLY_EXEC);
 
-       if (!boot_cpu_has(X86_FEATURE_SEP)) {
+#ifdef CONFIG_X86_SYSENTER
+       if (boot_cpu_has(X86_FEATURE_SEP)) {
                memcpy(page,
-                      &vsyscall_int80_start,
-                      &vsyscall_int80_end - &vsyscall_int80_start);
+                      &vsyscall_sysenter_start,
+                      &vsyscall_sysenter_end - &vsyscall_sysenter_start);
                return 0;
        }
+#endif
 
        memcpy(page,
-              &vsyscall_sysenter_start,
-              &vsyscall_sysenter_end - &vsyscall_sysenter_start);
+              &vsyscall_int80_start,
+              &vsyscall_int80_end - &vsyscall_int80_start);
 
        return 0;
 }
index f51c894a7da525a28bd9d84137f1736ff03e63fd..da2d48e1784541690f25ef095e46b7931b05702d 100644 (file)
@@ -97,7 +97,9 @@
 struct pt_regs * FASTCALL(save_v86_state(struct kernel_vm86_regs * regs));
 struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs)
 {
+#ifndef CONFIG_X86_NO_TSS
        struct tss_struct *tss;
+#endif
        struct pt_regs *ret;
        unsigned long tmp;
 
@@ -122,7 +124,9 @@ struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs)
                do_exit(SIGSEGV);
        }
 
+#ifndef CONFIG_X86_NO_TSS
        tss = &per_cpu(init_tss, get_cpu());
+#endif
        current->thread.esp0 = current->thread.saved_esp0;
        current->thread.sysenter_cs = __KERNEL_CS;
        load_esp0(tss, &current->thread);
@@ -251,7 +255,9 @@ out:
 
 static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk)
 {
+#ifndef CONFIG_X86_NO_TSS
        struct tss_struct *tss;
+#endif
 /*
  * make sure the vm86() system call doesn't try to do anything silly
  */
@@ -295,7 +301,9 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
        savesegment(fs, tsk->thread.saved_fs);
        savesegment(gs, tsk->thread.saved_gs);
 
+#ifndef CONFIG_X86_NO_TSS
        tss = &per_cpu(init_tss, get_cpu());
+#endif
        tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
        if (cpu_has_sep)
                tsk->thread.sysenter_cs = 0;
index b403890fe39b35a54ea8f1312790d6fc6434cc6f..432aa46649cc7a25cc3bf1aae71f2343cba18169 100644 (file)
@@ -7,9 +7,11 @@ vsyscall_int80_start:
        .incbin "arch/i386/kernel/vsyscall-int80.so"
 vsyscall_int80_end:
 
+#ifdef CONFIG_X86_SYSENTER
        .globl vsyscall_sysenter_start, vsyscall_sysenter_end
 vsyscall_sysenter_start:
        .incbin "arch/i386/kernel/vsyscall-sysenter.so"
 vsyscall_sysenter_end:
+#endif
 
 __FINIT
index e903b666c8173dffcce65aec9aff31abca4efbae..7d9ffc75d2d228c99f296dd5d612aacdf4ee5fc5 100644 (file)
@@ -61,6 +61,7 @@ __asm__ __volatile__ ("movw %w3,0(%2)\n\t" \
        "rorl $16,%1" \
        : "=m"(*(n)) : "q" (addr), "r"(n), "ir"(limit), "i"(type))
 
+#ifndef CONFIG_X86_NO_TSS
 static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, void *addr)
 {
        _set_tssldt_desc(&get_cpu_gdt_table(cpu)[entry], (int)addr,
@@ -68,6 +69,7 @@ static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, void *ad
 }
 
 #define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
+#endif
 
 static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int size)
 {
index 2b78658f1bead492c077ff2a82b49faaff4945fb..8ff4c15cb9cd8c6f7b21443d06b3af49bca8cf6e 100644 (file)
@@ -91,8 +91,10 @@ struct cpuinfo_x86 {
 
 extern struct cpuinfo_x86 boot_cpu_data;
 extern struct cpuinfo_x86 new_cpu_data;
+#ifndef CONFIG_X86_NO_TSS
 extern struct tss_struct doublefault_tss;
 DECLARE_PER_CPU(struct tss_struct, init_tss);
+#endif
 
 #ifdef CONFIG_SMP
 extern struct cpuinfo_x86 cpu_data[];
@@ -343,7 +345,9 @@ extern int bootloader_type;
 #define IO_BITMAP_BITS  65536
 #define IO_BITMAP_BYTES (IO_BITMAP_BITS/8)
 #define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long))
+#ifndef CONFIG_X86_NO_TSS
 #define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap)
+#endif
 #define INVALID_IO_BITMAP_OFFSET 0x8000
 #define INVALID_IO_BITMAP_OFFSET_LAZY 0x9000
 
@@ -401,6 +405,7 @@ typedef struct {
 
 struct thread_struct;
 
+#ifndef CONFIG_X86_NO_TSS
 struct tss_struct {
        unsigned short  back_link,__blh;
        unsigned long   esp0;
@@ -446,6 +451,7 @@ struct tss_struct {
         */
        unsigned long stack[64];
 } __attribute__((packed));
+#endif
 
 #define ARCH_MIN_TASKALIGN     16
 
@@ -482,6 +488,7 @@ struct thread_struct {
        .io_bitmap_ptr = NULL,                                          \
 }
 
+#ifndef CONFIG_X86_NO_TSS
 /*
  * Note that the .io_bitmap member must be extra-big. This is because
  * the CPU will access an additional byte beyond the end of the IO
@@ -504,8 +511,11 @@ static inline void load_esp0(struct tss_struct *tss, struct thread_struct *threa
                tss->ss1 = thread->sysenter_cs;
                wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
        }
-       HYPERVISOR_stack_switch(tss->ss0, tss->esp0);
 }
+#else
+#define load_esp0(tss, thread) \
+       HYPERVISOR_stack_switch(__KERNEL_DS, (thread)->esp0)
+#endif
 
 #define start_thread(regs, new_eip, new_esp) do {              \
        __asm__("movl %0,%%fs ; movl %0,%%gs": :"r" (0));       \